/*
 * Copyright (c) 2022, yifengling0. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. No personal names or organizations' names associated with the
 *    Atomthreads project may be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "atom.h"
#define ATOM_NONE_STANDARDIO
#include "drv_pin.h"
#include "drv_spi.h"
#undef OK
#include "driver/spi_master.h" // 引入SPI主设备驱动程序的头文件
#include "syslog.h"

spi_device_handle_t handle; // SPI设备的句柄

static int esp32_spi_xfer(SpiBase* dev, const void* send_buf, void* recv_buf, size_t length)
{
    Esp32Spi* pDrv = (Esp32Spi*)dev;

    spi_transaction_t trans_desc;
    trans_desc.addr = 0;             // 地址阶段的值，0表示没有地址阶段
    trans_desc.cmd = 0;              // 命令阶段的值，0表示没有命令阶段
    trans_desc.flags = 0;            // 事务的标志，0表示没有特殊标志
    trans_desc.length = length;       // 事务的长度，单位为位
    trans_desc.rxlength = recv_buf == NULL ? 0 : length;         // 接收的长度，0表示没有接收数据
    trans_desc.tx_buffer = send_buf;  // 发送缓冲区的指针
    trans_desc.rx_buffer = recv_buf;  // 接收缓冲区的指

    if (pDrv->Protected.autoCs) {
        PinWrite(pDrv->Protected.csPin, PIN_LOW);
    }

    spi_device_transmit(handle, &trans_desc);

    if (pDrv->Protected.autoCs) {
        PinWrite(pDrv->Protected.csPin, PIN_HIGH);
    }

    return OK;
}
static Esp32Spi _spi;

// 初始化SPI总线
spi_bus_config_t bus_config = {
    .mosi_io_num = 13,
    .miso_io_num = 12,
    .sclk_io_num = 14,
    .quadwp_io_num = -1,
    .quadhd_io_num = -1,
    
};

spi_device_interface_config_t dev_config = {
    .mode = 0,                  // SPI模式，0表示模式0
    .clock_speed_hz = 10000000, // SPI时钟速度，单位为Hz
    .spics_io_num = -1,          // CS引脚的GPIO编号
    .queue_size = 7,            // 事务队列的大小，这里设置为7
};

void Esp32SpiCreate(void)
{
    _spi.Protected.autoCs = 0;
    _spi.Protected.csPin = dev_config.spics_io_num;

    if (_spi.Protected.autoCs) {
        PinMode(_spi.Protected.csPin, PIN_MODE_OUTPUT);
    }
    
    spi_bus_initialize(SPI2_HOST, &bus_config, SPI_DMA_CH_AUTO);
    spi_bus_add_device(SPI2_HOST, &dev_config, &handle);

    SpiCreate(&_spi.super, "hspi",
         0, (dev_config.mode & 0x01), (dev_config.mode & 0x02), 8, 8, dev_config.clock_speed_hz, esp32_spi_xfer);

    SYSLOG(LOG_INFO, "hspi module initlized");
}